package com.ynding.spring.physical.redis.meta.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ynding.spring.physical.redis.meta.lock.DistributedLock;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * <p> </p>
 *
 * @author ynding
 * @version 2022/6/14
 **/
@Api(tags = "redis分布式锁测试类")
@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("/lock")
public class RedisDistributedLockController {

    private final DistributedLock distributedLock;
    private final RedissonClient redissonClient;

    /**
     * 锁id
     */
    private final static String LOCK_ID = "syncCargo";

    @PostMapping("/syncCargo")
    @ApiOperation(value = "物料主数据接口")
    public ResponseEntity<Boolean> syncCargo(@RequestBody(required = false) Object request) {
        log.info("物料主数据接口入参request:{}", JSONObject.toJSONString(request));
        try {
            boolean lock = distributedLock.getLock(LOCK_ID, 120 * 1000);
            if (lock) {
                log.info("获取到锁，执行物料主数据同步任务！");
                System.out.println(request);
                log.info("任务完成，释放锁！");
                distributedLock.releaseLock(LOCK_ID);
                return ResponseEntity.ok(true);
            }
            log.info("物料主数据正在同步！");
            return ResponseEntity.badRequest().eTag("物料主数据正在同步!").build();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(StrUtil.format("同步物料主数据失败：{}", e.getMessage()));
            return ResponseEntity.badRequest().eTag(e.getMessage()).build();
        }
    }

    @PostMapping("/redisson/lock")
    @ApiOperation(value = "使用redisson实现分布式锁")
    public ResponseEntity<Boolean> redissonLock(@RequestBody(required = false) Object request) {
        log.info("数据接口入参request:{}", JSONObject.toJSONString(request));
        //定义锁
        RLock lock = redissonClient.getLock(LOCK_ID);
        try {
            //尝试加锁,最大等待时间300毫秒，上锁30毫秒自动解锁
            if (lock.tryLock(300, 30, TimeUnit.MILLISECONDS)) {
                log.info("线程:" + Thread.currentThread().getName() + "获得了锁");
                System.out.println(request);
                return ResponseEntity.ok(true);
            }
            return ResponseEntity.badRequest().eTag("物料主数据正在同步!").build();
        } catch (Exception e) {
            log.error("程序执行异常:{}", e);
            return ResponseEntity.badRequest().eTag(e.getMessage()).build();
        } finally {
            log.info("线程:" + Thread.currentThread().getName() + "准备释放锁");
            //释放锁
            lock.unlock();
        }
    }
}
